package com.zhiwen.service.impl;

import com.zhiwen.common.enums.NotificationType;
import com.zhiwen.config.RabbitMQConfig;
import com.zhiwen.domain.event.NotificationEvent;
import com.zhiwen.service.NotificationProducer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 基于RabbitMQ的通知生产者实现
 */
@Slf4j
@Service
public class RabbitMQNotificationProducer implements NotificationProducer {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Override
    @Retryable(value = {AmqpException.class}, maxAttempts = 3, backoff = @Backoff(delay = 1000, multiplier = 2))
    //sendquestionAnswerdewerdification
    public void sendQuestionAnsweredNotification(Long questionId, Long answerId, Long receiverId, Long senderId) {
        NotificationEvent event = NotificationEvent.builder()
                .type(NotificationType.QUESTION_ANSWERED.getValue())
                .questionId(questionId)
                .answerId(answerId)
                .receiverId(receiverId)
                .senderId(senderId)
                .build();

        // 使用主题交换机，问题相关通知路由
        sendToTopicExchange(event, "question.answered");
    }



    @Override
    @Retryable(value = {AmqpException.class}, maxAttempts = 3, backoff = @Backoff(delay = 1000, multiplier = 2))
    public void sendAnswerCommentedNotification(Long answerId, Long commentId, Long receiverId, Long senderId) {
        NotificationEvent event = NotificationEvent.builder()
                .type(NotificationType.ANSWER_COMMENTED.getValue())
                .answerId(answerId)
                .commentId(commentId)
                .receiverId(receiverId)
                .senderId(senderId)
                .build();

        // 使用主题交换机，评论相关通知路由
        sendToTopicExchange(event, "comment.created");

    }

    @Override
    @Retryable(value = {AmqpException.class}, maxAttempts = 3, backoff = @Backoff(delay = 1000, multiplier = 2))
    public void sendAnswerAcceptedNotification(Long questionId, Long answerId, Long receiverId, Long senderId) {
        NotificationEvent event = NotificationEvent.builder()
                .type(NotificationType.ANSWER_ACCEPTED.getValue())
                .questionId(questionId)
                .answerId(answerId)
                .receiverId(receiverId)
                .senderId(senderId)
                .build();

        // 使用主题交换机，回答相关通知路由
        sendToTopicExchange(event, "answer.accepted");
    }

    @Override
    @Retryable(value = {AmqpException.class}, maxAttempts = 3, backoff = @Backoff(delay = 1000, multiplier = 2))
    public void sendContentReviewedNotification(Integer contentType, Long contentId, Long receiverId, Integer reviewResult, String remark) {
        NotificationEvent event = NotificationEvent.builder()
                .type(NotificationType.CONTENT_REVIEWED.getValue())
                .contentType(contentType)
                .contentId(contentId)
                .receiverId(receiverId)
                .reviewResult(reviewResult)
                .remark(remark)
                .build();

        // 根据内容类型选择路由
        String routingSuffix;
        switch (contentType) {
            case 1: // 问题
                routingSuffix = "question.reviewed";
                break;
            case 2: // 回答
                routingSuffix = "answer.reviewed";
                break;
            case 3: // 评论
                routingSuffix = "comment.reviewed";
                break;
            default:
                routingSuffix = "content.reviewed";
        }

        // 使用主题交换机，内容审核通知路由
        sendToTopicExchange(event, routingSuffix);
    }

    @Override
    @Retryable(value = {AmqpException.class}, maxAttempts = 3, backoff = @Backoff(delay = 1000, multiplier = 2))
    public void sendSystemNotification(String title, String content, Long receiverId) {
        NotificationEvent event = NotificationEvent.builder()
                .type(NotificationType.SYSTEM_NOTICE.getValue())
                .title(title)
                .content(content)
                .receiverId(receiverId)
                .build();

        // 使用主题交换机，系统通知路由
        sendToTopicExchange(event, "system.notice");
    }

    @Override
    @Async
    public void sendSystemNotificationToMultiUsers(String title, String content, List<Long> receiverIds) {
        if (receiverIds == null || receiverIds.isEmpty()) {
            log.warn("接收者ID列表为空，无法发送系统通知");
            return;
        }

        // 构建通知事件列表
        List<NotificationEvent> events = receiverIds.stream()
                .map(receiverId -> NotificationEvent.builder()
                        .type(NotificationType.SYSTEM_NOTICE.getValue())
                        .title(title)
                        .content(content)
                        .receiverId(receiverId)
                        .build())
                .collect(Collectors.toList());

        // 批量发送通知
        sendBatchNotificationEvents(events);
    }

    @Override
    @Retryable(value = {AmqpException.class}, maxAttempts = 3, backoff = @Backoff(delay = 1000, multiplier = 2))
    public void sendNotificationEvent(NotificationEvent event) {
        if (event == null) {
            log.warn("通知事件为空，无法发送");
            return;
        }

        // 根据通知类型确定路由后缀
        String routingSuffix = getRoutingSuffixByType(event);

        // 发送通知
        sendToTopicExchange(event, routingSuffix);
    }

    @Override
    @Async
    public void sendBatchNotificationEvents(List<NotificationEvent> events) {
        if (events == null || events.isEmpty()) {
            log.warn("通知事件列表为空，无法批量发送");
            return;
        }

        try {
            // 使用批量队列一次性发送多条通知
            rabbitTemplate.convertAndSend(
                    RabbitMQConfig.NOTIFICATION_EXCHANGE,
                    RabbitMQConfig.BATCH_NOTIFICATION_ROUTING_KEY,
                    events,
                    message -> {
                        message.getMessageProperties().setContentType("application/json");
                        message.getMessageProperties().setHeader("batch", true);
                        message.getMessageProperties().setHeader("count", events.size());
                        return message;
                    },
                    new CorrelationData(UUID.randomUUID().toString())
            );

            log.info("批量发送通知完成，共发送{}条通知", events.size());
        } catch (Exception e) {
            log.error("批量发送通知失败", e);
            // 如果批量发送失败，回退到单个发送
            log.warn("批量发送失败，回退到单个发送");
            events.forEach(this::sendNotificationEvent);
        }
    }

    @Override
    @Retryable(value = {AmqpException.class}, maxAttempts = 3, backoff = @Backoff(delay = 1000, multiplier = 2))
    public void sendContentLikedNotification(Integer contentType, Long contentId, Long receiverId, Long senderId) {
        NotificationEvent event = NotificationEvent.builder()
                .type(NotificationType.CONTENT_LIKED.getValue())
                .contentType(contentType)
                .contentId(contentId)
                .receiverId(receiverId)
                .senderId(senderId)
                .build();

        // 使用主题交换机，点赞相关通知路由
        sendToTopicExchange(event, "like.content");
    }

    @Override
    @Retryable(value = {AmqpException.class}, maxAttempts = 3, backoff = @Backoff(delay = 1000, multiplier = 2))
    public void sendUserFollowedNotification(Long receiverId, Long senderId) {
        NotificationEvent event = NotificationEvent.builder()
                .type(NotificationType.USER_FOLLOWED.getValue())
                .receiverId(receiverId)
                .senderId(senderId)
                .build();

        // 使用主题交换机，关注相关通知路由
        sendToTopicExchange(event, "follow.user");
    }

    /**
     * 发送通知到主题交换机
     *
     * @param event 通知事件
     * @param routingSuffix 路由后缀
     */
    private void sendToTopicExchange(NotificationEvent event, String routingSuffix) {
        try {
            String messageId = UUID.randomUUID().toString();
            CorrelationData correlationData = new CorrelationData(messageId);
            String routingKey = RabbitMQConfig.NOTIFICATION_TOPIC_PREFIX + routingSuffix;

            log.info("发送通知消息到主题交换机: {}, routingKey: {}, messageId: {}", event, routingKey, messageId);

            // 发送到主题交换机，确保消息只进入一个队列
            rabbitTemplate.convertAndSend(
                    RabbitMQConfig.NOTIFICATION_TOPIC_EXCHANGE,
                    routingKey,
                    event,
                    getMessagePostProcessor(event),
                    correlationData
            );

            // 注意：不要发送到通用队列，避免消息重复处理
        } catch (Exception e) {
            log.error("发送通知到主题交换机失败", e);
            throw e; // 抛出异常以触发重试机制
        }
    }

    /**
     * 获取消息后处理器，设置消息属性
     *
     * @param event 通知事件
     * @return 消息后处理器
     */
    private MessagePostProcessor getMessagePostProcessor(NotificationEvent event) {
        return message -> {
            // 设置消息属性
            message.getMessageProperties().setContentType("application/json");
            message.getMessageProperties().setPriority(getPriority(event));
            message.getMessageProperties().setExpiration("86400000"); // 24小时过期

            // 添加自定义头信息
            message.getMessageProperties().setHeader("notificationType", event.getType());
            if (event.getReceiverId() != null) {
                message.getMessageProperties().setHeader("receiverId", event.getReceiverId().toString());
            }

            return message;
        };
    }

    /**
     * 根据通知类型获取优先级
     *
     * @param event 通知事件
     * @return 优先级 (0-9)
     */
    private int getPriority(NotificationEvent event) {
        switch (event.getType()) {
            case 3: // 回答被采纳
                return 8;
            case 5: // 系统通知
                return 9;
            case 4: // 内容审核
                return 7;
            case 1: // 问题回答
                return 6;
            case 2: // 回答评论
                return 5;
            case 6: // 内容点赞
                return 4;
            case 7: // 用户关注
                return 4;
            default:
                return 0;
        }
    }

    /**
     * 根据通知类型获取路由后缀
     *
     * @param event 通知事件
     * @return 路由后缀
     */
    private String getRoutingSuffixByType(NotificationEvent event) {
        if (event == null || event.getType() == null) {
            return "default";
        }

        switch (event.getType()) {
            case 1: // 问题回答
                return "question.answered";
            case 2: // 回答评论
                return "comment.created";
            case 3: // 回答被采纳
                return "answer.accepted";
            case 4: // 内容审核
                Integer contentType = event.getContentType();
                if (contentType == null) {
                    return "content.reviewed";
                }

                switch (contentType) {
                    case 1:
                        return "question.reviewed";
                    case 2:
                        return "answer.reviewed";
                    case 3:
                        return "comment.reviewed";
                    default:
                        return "content.reviewed";
                }
            case 5: // 系统通知
                return "system.notice";
            case 6: // 内容点赞
                return "like.content";
            case 7: // 用户关注
                return "follow.user";
            default:
                return "default";
        }
    }
}
